#pragma once

class CEX Buffer:public Object
{
	// Pointer to the actual buffer data
	char* _buf;

	// Size of the allocated buffer
	int _size;

public:
	
	virtual const char* __getName(){return "Buffer";}
	
	// Constructor
	// Create an empty buffer
	Buffer()
	{
		_buf=NULL;
		_size=0;
	}

	// Constructor
	// Create a fixed-size buffer
	// size: Size, in bytes, of the buffer to create
	Buffer(int size)
	{
		ASSERT(size>=0,"Invalid Buffer Size")

		// Allocate a block of the requested size
		_size = size;
		_buf = (char*)malloc(size);
	}

	// Copy constructor
	// o: Buffer to copy
	Buffer(const Buffer& o)
	{
		// Allocate a block the same size
		_size = o._size;
		_buf = (char*)malloc(_size);

		// Copy the data
		memcpy(_buf,o._buf,_size);
	}

	// Constructor
	// Copy data from a provided pointer
	// o: Buffer to copy the data from
	// size: Number of bytes to allocate/copy
	Buffer(const char* o,int size)
	{
		ASSERT(size>=0,"Invalid Buffer Size")

		// Allocate the block
		_size = size;
		_buf = (char*)malloc(size);

		// Copy the data
		memcpy(_buf,o,size);
	}

	// Destructor
	~Buffer()
	{
		// Free the buffer, if allocated
		if(_buf)
			free(_buf);
	}

	// Resize the buffer
	// newSize: New size of the buffer, in bytes
	// keep: Wether to keep the previous data or not.  If set to true,
	//       the data will be copied to the new buffer, otherwise it
	//       will be discarded
	void resize(int newSize,bool keep)
	{
		ASSERT(newSize>=0,"Invalid Buffer Size")

		// Mark the new size
		_size = newSize;

		if(keep)
		{
			// Re-allocate the block, keeping the previous data
			_buf = (char*)realloc(_buf,newSize);
		}
		else
		{
			// Free the old buffer
			if(_buf)
				free(_buf);

			// Re-allocate using the new size
			_buf = (char*)malloc(newSize);
		}
	}

	// Free the buffer
	void clear()
	{
		// Free the buffer, if allocated
		if(_buf)
			free(_buf);

		// Mark the buffer as empty
		_buf = NULL;
		_size = 0;
	}

	// Array operator
	// Retrieve a single char from the buffer
	// index: Index of the byte to retrieve
	// Returns: The character at 'index'
	char operator[](int index) const
	{
		ASSERT(index>=0 && index<_size,"Index out of range")

		// Simply return the requested character
		return _buf[index];
	}

	// Affectation operator
	// Copy the provided buffer into our own
	// o: Buffer to copy
	Buffer& operator=(const Buffer& o)
	{
		// Clear any previous buffer
		clear();

		// Allocate a new buffer, the same size as the one we're copying
		_size = o._size;
		_buf = (char*)malloc(_size);

		// Copy the data
		memcpy(_buf,o._buf,_size);
		
		return *this;
	}
	
	// Return a raw pointer to the buffer
	// NOTE: If the buffer is resized using Buffer::resize(), the pointer
	//       returned by this operator becomes invalid.
	operator char*() const
	{
		return _buf;
	}

	// Return the size of the buffer
	int getSize() const
	{
		return _size;
	}
};


